import { Context } from '../../../src/common';
import * as t from 'assert';
import { parseSource } from '../../../src/parser';
import { fail } from '../../test-utils';

describe('Miscellaneous - Escaped keywords', () => {
  for (const arg of [
    '(\\u0069mplements = 1);',
    'var impl\\u0065ments = 1;',
    'var { impl\\u0065ments  } = {};',
    '(\\u0069nterface = 1);',
    '({ def\\u0061ult: 0 })',
    '({ def\\u{61}ult: 0 })',
    'foo = {}; foo.def\\u{61}ult = 3;',
    'var int\\u0065rface = 1;',
    'var { int\\u0065rface  } = {};',
    '(p\\u0061ckage = 1);',
    'var packa\\u0067e = 1;',
    'var { packa\\u0067e  } = {};',
    '(p\\u0072ivate = 1);',
    'var p\\u0072ivate;',
    'var { p\\u0072ivate } = {};',
    '(prot\\u0065cted);',
    'var prot\\u0065cted = 1;',
    'var { prot\\u0065cted  } = {};',
    '(publ\\u0069c);',
    'var publ\\u0069c = 1;',
    'var { publ\\u0069c } = {};',
    '(st\\u0061tic);',
    'var st\\u0061tic = 1;',
    'var { st\\u0061tic } = {};',
    'l\\u0065t\na',
    'if (true) l\\u0065t: ;',
    'function l\\u0065t() { }',
    '(function l\\u0065t() { })',
    'async function l\\u0065t() { }',
    '(async function l\\u0065t() { })',
    '(class { get st\\u0061tic() {}})',
    '(class { set st\\u0061tic(x){}});',
    '(class { *st\\u0061tic() {}});',
    '(class { st\\u0061tic(){}});',
    '(class { static get st\\u0061tic(){}});',
    '(class { static set st\\u0061tic(x) {}});',
    'l\\u0065t => 42',
    '(\\u0061sync ())',
    'async l\\u0065t => 42',
    'function packag\\u0065() {}',
    'function impl\\u0065ments() {}',
    'function privat\\u0065() {}',
    '(y\\u0069eld);',
    'var impl\\u0065ments = 1;',
    'var { impl\\u0065ments  } = {};',
    '(\\u0069nterface = 1);',
    'var int\\u0065rface = 1;',
    'var { int\\u0065rface  } = {};',
    '(p\\u0061ckage = 1);',
    'var packa\\u0067e = 1;',
    'var { packa\\u0067e  } = {};',
    '(p\\u0072ivate = 1);',
    'var p\\u0072ivate;',
    'var { p\\u0072ivate } = {};',
    '(prot\\u0065cted);',
    'var prot\\u0065cted = 1;',
    'var { prot\\u0065cted  } = {};',
    '(publ\\u0069c);',
    'var C = class { get "def\\u{61}ult"() { return "get string"; } set "def\\u{61}ult"(param) { stringSet = param; } };',
    'var publ\\u0069c = 1;',
    'var { publ\\u0069c } = {};',
    '(st\\u0061tic);',
    'var st\\u0061tic = 1;',
    'var { st\\u0061tic } = {};',
    'var y\\u0069eld = 1;',
    'var { y\\u0069eld } = {};',
    'class aw\\u0061it {}',
    'aw\\u0061it: 1;',
    'function *a(){({yi\\u0065ld: 0})}',
    '\\u0061sync',
    'l\\u0065t\na',
    'l\\u0065t',
    `function a() {
      \\u0061sync
      p => {}
    }`,
    `(function a() {
      \\u0061sync
      p => {}
    })`,
    `async function a() {
      \\u0061sync
      p => {}
    }`
  ]) {
    it(`${arg}`, () => {
      t.doesNotThrow(() => {
        parseSource(`${arg}`, undefined, Context.None);
      });
    });
  }
  //
  fail('Miscellaneous - Escaped identifiers (failures)', [
    ['(x === n\\u0075ll);', Context.None],
    ['var x = n\\u0075ll;', Context.None],
    ['var x = { interf\\u0061ce } = { interface: 42 };', Context.Strict | Context.Module],
    ['var x = ({ w\\u0069th }) => {};', Context.None],
    ['var n\\u0075ll = 1;', Context.None],
    ['var { n\\u0075ll } = { 1 };', Context.None],
    ['n\\u0075ll = 1;', Context.None],
    ['(x === tr\\u0075e);', Context.None],
    ['var x = tr\\u0075e;', Context.None],
    ['var tr\\u0075e = 1;', Context.None],
    // ['({ def\\u0061ult })', Context.None],
    ['0, { def\\u{61}ult: x } = { default: 42 };', Context.None],
    ['var y = { bre\\u0061k: x } = { break: 42 };', Context.None],
    ['var y = { c\\u0061se: x } = { case: 42 };', Context.None],
    ['var y = { c\\u0061tch: x } = { catch: 42 };', Context.None],
    ['var y = { \\u0063onst: x } = { const: 42 };', Context.None],
    ['var y = { \\u0064ebugger: x } = { debugger: 42 };', Context.None],
    ['var { tr\\u0075e } = {};', Context.None],
    ['tr\\u0075e = 1;', Context.None],
    ['(x === f\\u0061lse);', Context.None],
    ['var x = f\\u0061lse;', Context.None],
    ['var f\\u0061lse = 1;', Context.None],
    ['var { f\\u0061lse } = {};', Context.None],
    ['f\\u0061lse = 1;', Context.None],
    ['switch (this.a) { c\\u0061se 6: break; }', Context.None],
    ['try { } c\\u0061tch (e) {}', Context.None],
    ['switch (this.a) { d\\u0065fault: break; }', Context.None],
    ['class C \\u0065xtends function B() {} {}', Context.None],
    ['for (var a i\\u006e this) {}', Context.None],
    ['if (this \\u0069nstanceof Array) {}', Context.None],
    ['(n\\u0065w function f() {})', Context.None],
    ['(typ\\u0065of 123)', Context.None],
    ['const [l\\u0065t] = 1', Context.None],
    ['const [l\\u0065t] = 1', Context.None],
    ['(function() {for (let l\\u0065t in {}) {}})()', Context.None],
    ['cl\\u0061ss Foo {}', Context.None],
    ['export function br\\u0065ak() {}', Context.Strict | Context.Module],
    ['class aw\\u0061it {}', Context.Strict | Context.Module],
    ['class l\\u0065t {}', Context.Strict],
    ['class st\\u0061tic {}', Context.Strict],
    ['class st\\u0061tic {}', Context.None],
    ['class yi\\u0065ld {}', Context.Strict],
    ['aw\\u0061it: 1;', Context.Strict | Context.Module],
    ['a(1,2\\u0063onst foo = 1;', Context.None],
    ['let l\\u0065t = 1', Context.None],
    ['const l\\u0065t = 1', Context.None],
    ['let [l\\u0065t] = 1', Context.None],
    ['const [l\\u0065t] = 1', Context.None],
    ['for (let l\\u0065t in {}) {}', Context.None],
    ['(async ()=>{\\u0061wait 100})()', Context.None],
    ['(async ()=>{var \\u0061wait = 100})()', Context.None],
    ['\\u0063o { } while(0)', Context.None],
    ['v\\u0061r', Context.None],
    ['({\\u0067et get(){}})', Context.None],
    ['({\\u0073et set(){}})', Context.None],
    ['import* \\u0061s foo from "./icefapper.js";', Context.Strict | Context.Module],
    ['void \\u0061sync function* f(){};', Context.Strict | Context.Module],
    ['a(1,2\\u0063onst foo = 1;', Context.None],
    ['\\u0063o { } while(0)', Context.None],
    ['cl\\u0061ss Foo {}', Context.None],
    ['var {var:v\\u0061r} = obj', Context.None],
    ['[v\\u{0061}r] = obj', Context.None],
    ['function a({var:v\\u{0061}r}) { }', Context.None],
    ['(function v\\u0061r() { })', Context.None],
    ['(function a(v\\u0061r) { })', Context.None],
    ['(function a({v\\u{0061}r}) { })', Context.None],
    ['(function a([{v\\u{0061}r}]) { })', Context.None],
    ['(function a([[v\\u{0061}r]]) { })', Context.None],
    ['(function a({ hello: [v\\u{0061}r]}) { })', Context.None],
    ['(function a({ 0: {var:v\\u{0061}r}}) { })', Context.None],
    ['v\\u0061r', Context.None],
    ['var v\\u0061r = 2000000;', Context.None],
    ['var v\\u{0061}r = 2000000', Context.None],
    ['try { } catch(v\\u{0061}r) { }', Context.None],
    ['var obj = { async method() { void \\u0061wait; } };', Context.Strict],
    ['class C { async *gen() { void \\u0061wait; }}', Context.None],
    ['async() => { void \\u0061wait; };', Context.None],
    ['{for(o i\\u006E {}){}}', Context.None],
    ['class X { se\\u0074 x(value) {} }', Context.None],
    ['class X { st\\u0061tic y() {} }', Context.None],
    ['(function* () { y\\u0069eld 10 })', Context.None],
    ['({ \\u0061sync x() { await x } })', Context.None],
    ['export \\u0061sync function y() { await x }', Context.Module],
    ['{for(o i\\u006E {}){}}', Context.None],
    ['impleme\\u{006E}ts', Context.Strict],
    ['impleme\\u{006E}ts', Context.Strict | Context.Module],
    [`'use strict'; impleme\\u{006E}ts`, Context.None],
    ['[th\\u{69}s] = []', Context.None],
    ['th\\u{69}s', Context.None],
    ['[f\\u0061lse] = []', Context.None],
    ['f\\u0061lse', Context.None],
    ['class C { static async method() { void \\u0061wait; }}', Context.None],
    ['while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }', Context.None],
    ['(function a({ hello: {var:v\\u{0061}r}}) { })', Context.None],
    ['[v\\u{0061}r] = obj', Context.None],
    ['t\\u0072y { true } catch (e) {}', Context.None],
    ['var x = typ\\u0065of "blah"', Context.None],
    ['v\\u0061r a = true', Context.None],
    ['thi\\u0073 = 123;', Context.None],
    ['i\\u0066 (false) {}', Context.None],
    ['for (var i = 0; i < 100; ++i) { br\\u0065ak; }', Context.None],
    ['cl\\u0061ss Foo {}', Context.None],
    ['var f = f\\u0075nction() {}', Context.None],
    ["thr\\u006fw 'boo';", Context.None],
    ['var x = { n\\u0065w } = { new: 42 };', Context.None],
    ['var x = { privat\\u0065 } = { private: 42 };', Context.Strict | Context.Module],
    ['var x = { sup\\u0065r } = { super: 42 };', Context.Strict | Context.Module],
    ['var x = { v\\u0061r } = { var: 42 };', Context.Strict | Context.Module],
    ['var x = { privat\\u0065 } = { private: 42 };', Context.Strict | Context.Module],
    ['w\\u0069th (this.scope) { }', Context.None],
    ['n\\u0075ll = 1;', Context.None],
    ['(x === tr\\u0075e);', Context.None],
    ['do { ; } wh\\u0069le (true) { }', Context.None],
    ['class X { st\\u0061tic y() {} }', Context.None],
    ['class C { st\\u0061tic set bar() {} }', Context.None],
    ['class C { st\\u0061tic *bar() {} }', Context.None],
    ['let l\\u0065t = 1', Context.None],
    ['const l\\u0065t = 1', Context.None],
    ['let [l\\u0065t] = 1', Context.None],
    ['const [l\\u0065t] = 1', Context.None],
    ['if ("foo" \\u0069n this) {}', Context.None],
    ['if (this \\u0069nstanceof Array) {}', Context.None],
    ['(n\\u0065w function f() {})', Context.None],
    ['(typ\\u0065of 123)', Context.None],
    ['var y = { c\\u0061se: x } = { case: 42 };', Context.None],
    ['({ def\\u{61}ult }) => 42;', Context.None],
    ['0, { def\\u{61}ult } = { default: 42 };', Context.None],
    ['var x = ({ bre\\u0061k }) => {};', Context.None],
    ['var x = ({ tr\\u0079 }) => {};', Context.None],
    ['var x = ({ typ\\u0065of }) => {};', Context.None],
    ['def\\u0061ult', Context.None],
    ['var x = { \\u0069mport } = { import: 42 };', Context.Strict | Context.Module],
    ['(v\\u006fid 0)', Context.None],
    ['aw\\u0061it: 1;', Context.Module | Context.Strict],
    ['var \\u{65}\\u{6e}\\u{75}\\u{6d} = 123;', Context.None],
    ['do { ; } wh\\u0069le (true) { }', Context.None],
    ['(function*() { return (n++, y\\u0069eld 1); })()', Context.None],
    ['var \\u0064elete = 123;', Context.None],
    ['var \\u{62}\\u{72}\\u{65}\\u{61}\\u{6b} = 123;', Context.None],
    ['var \\u0062\\u0072\\u0065\\u0061\\u006b = 123;;', Context.None],
    ['var \\u{63}ase = 123;', Context.None],
    ['var \\u{63}atch = 123;', Context.None],
    ['var x = { \\u0066unction } = { function: 42 };', Context.None],
    ['var \\u{63}ontinue = 123;', Context.None],
    ['var fina\\u{6c}ly = 123;', Context.None],
    ['var \\u{64}\\u{6f} = 123;', Context.None],
    ['var gen = async function *g() { yi\\u0065ld: ; };', Context.None],
    ['function *gen() { yi\\u0065ld: ; }', Context.None],
    ['(function *gen() { yi\\u0065ld: ; })', Context.None],
    ['i\\u0066 (0)', Context.None],
    ['var i\\u0066', Context.None],
    ['export {a \\u0061s b} from "";', Context.Strict | Context.Module],
    ['export {} fr\\u006fm "";', Context.Strict | Context.Module],
    ['for (a o\\u0066 b);', Context.None],
    ['class a { st\\u0061tic m(){} }', Context.None],
    ['var \\u{64}\\u{6f} = 123;', Context.None],
    ['(\\u0061sync function() { await x })', Context.None],
    ['(\\u0061sync () => { await x })', Context.None],
    ['\\u0061sync x => { await x }', Context.None],
    ['class X { \\u0061sync x() { await x } }', Context.None],
    ['class X { static \\u0061sync x() { await x } }', Context.None],
    ['export \\u0061sync function y() { await x }', Context.Strict | Context.Module],
    ['export default \\u0061sync function () { await x }', Context.Strict | Context.Module],
    ['for (x \\u006ff y) {}', Context.None],
    ['(async function() { aw\\u0061it x })', Context.None],
    ['(function*() { var y\\u0069eld = 1; })()', Context.None],
    ['(function*() { y\\u0069eld 1; })()', Context.None],
    ['wh\\u0069le (true) { }', Context.None],
    ['n\\u0065w function f() {}', Context.None],
    ['async () => { aw\\u{61}it: x }', Context.None],
    ['f\\u006fr (var i = 0; i < 10; ++i);', Context.None],
    ['try { } catch (e) {} f\\u0069nally { }', Context.None],
    ['d\\u0065bugger;', Context.None],
    ['if (d\\u006f { true }) {}', Context.None],
    ['\\u{74}rue', Context.None],
    ['var \\u{64}\\u{6f} = 123;', Context.None],
    ['var \\u{64}\\u{6f} = 123;', Context.Strict | Context.Module],
    ['a\\u{0022}b=1', Context.Strict],
    ['function impl\\u0065ments() {}', Context.Strict],
    ['function impl\\u0065ments() {}', Context.Strict | Context.Module],
    ['var gen = function *() { void yi\\u0065ld; };', Context.Strict | Context.Module],
    ['var gen = async function *g() { void \\u0061wait; };', Context.Strict | Context.Module],
    ['var gen = async function *g() { void \\u0061wait; };', Context.Strict | Context.Module],
    ['\\u0061sync function* f(){}', Context.Strict | Context.Module],
    ['class l\\u0065t {}', Context.Strict | Context.Module],
    ['class yi\\u0065ld {}', Context.Strict | Context.Module],
    ['class l\\u0065t {}', Context.Strict],
    ['class yi\\u0065ld {}', Context.Strict],
    ['class l\\u0065t {}', Context.None],
    ['class yi\\u0065ld {}', Context.None],
    ['class C { st\\u0061tic m() {} }', Context.None],
    ['var C = class aw\\u0061it {};', Context.Strict | Context.Module],
    ['var gen = async function *() { var yi\\u0065ld; };', Context.None],
    ['var obj = { *method() { void yi\\u0065ld; } };', Context.None],
    ['var gen = function *g() { yi\\u0065ld: ; };', Context.None],
    ['({ \\u0061sync* m(){}});', Context.None]
  ]);
});
